package com.takwolf.libgdx.core;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.utils.Disposable;
import com.takwolf.libgdx.tiled.TiledMap;

import java.util.HashMap;
import java.util.Map;

public class Asset implements Disposable {

    private Map<String, Texture> managedTextures = new HashMap<>();
    private Map<String, Music> managedMusics = new HashMap<>();
    private Map<String, Sound> managedSounds = new HashMap<>();
    private Map<String, TiledMap> managedTiledMaps = new HashMap<>();

    public Texture loadTexture(String internalPath) {
        return loadTexture(Gdx.files.internal(internalPath));
    }

    public Texture loadTexture(FileHandle fileHandle) {
        String path = fileHandle.path();
        Texture texture = managedTextures.get(path);
        if (texture == null) {
            texture = new Texture(fileHandle);
            managedTextures.put(path, texture);
        }
        return texture;
    }

    public void disposeTexture(Texture texture) {
        for (Map.Entry<String, Texture> entry : managedTextures.entrySet()) {
            if (entry.getValue().equals(texture)) {
                managedTextures.remove(entry.getKey());
                texture.dispose();
                return;
            }
        }
    }

    public void disposeTexture(String internalPath) {
        disposeTexture(Gdx.files.internal(internalPath));
    }

    public void disposeTexture(FileHandle fileHandle) {
        String path = fileHandle.path();
        Texture texture = managedTextures.get(path);
        if (texture != null) {
            managedTextures.remove(path);
            texture.dispose();
        }
    }

    public void disposeAllTexture() {
        for (Map.Entry<String, Texture> entry : managedTextures.entrySet()) {
            entry.getValue().dispose();
        }
        managedTextures.clear();
    }

    public Music loadMusic(String internalPath) {
        return loadMusic(Gdx.files.internal(internalPath));
    }

    public Music loadMusic(FileHandle fileHandle) {
        String path = fileHandle.path();
        Music music = managedMusics.get(path);
        if (music == null) {
            music = Gdx.audio.newMusic(Gdx.files.internal(path));
            managedMusics.put(path, music);
        }
        return music;
    }

    public void disposeMusic(Music music) {
        for (Map.Entry<String, Music> entry : managedMusics.entrySet()) {
            if (entry.getValue().equals(music)) {
                managedMusics.remove(entry.getKey());
                music.dispose();
                return;
            }
        }
    }

    public void disposeMusic(String internalPath) {
        disposeMusic(Gdx.files.internal(internalPath));
    }

    public void disposeMusic(FileHandle fileHandle) {
        String path = fileHandle.path();
        Music music = managedMusics.get(path);
        if (music != null) {
            managedMusics.remove(path);
            music.dispose();
        }
    }

    public void disposeAllMusic() {
        for (Map.Entry<String, Music> entry : managedMusics.entrySet()) {
            entry.getValue().dispose();
        }
        managedMusics.clear();
    }

    public Sound loadSound(String internalPath) {
        return loadSound(Gdx.files.internal(internalPath));
    }

    public Sound loadSound(FileHandle fileHandle) {
        String path = fileHandle.path();
        Sound sound = managedSounds.get(path);
        if (sound == null) {
            sound = Gdx.audio.newSound(Gdx.files.internal(path));
            managedSounds.put(path, sound);
        }
        return sound;
    }

    public void disposeSound(Sound sound) {
        for (Map.Entry<String, Sound> entry : managedSounds.entrySet()) {
            if (entry.getValue().equals(sound)) {
                managedSounds.remove(entry.getKey());
                sound.dispose();
                return;
            }
        }
    }

    public void disposeSound(String internalPath) {
        disposeSound(Gdx.files.internal(internalPath));
    }

    public void disposeSound(FileHandle fileHandle) {
        String path = fileHandle.path();
        Sound sound = managedSounds.get(path);
        if (sound != null) {
            managedSounds.remove(path);
            sound.dispose();
        }
    }

    public void disposeAllSound() {
        for (Map.Entry<String, Sound> entry : managedSounds.entrySet()) {
            entry.getValue().dispose();
        }
        managedSounds.clear();
    }

    public TiledMap loadTiledMap(String internalPath) {
        return loadTiledMap(Gdx.files.internal(internalPath));
    }

    public TiledMap loadTiledMap(FileHandle fileHandle) {
        String path = fileHandle.path();
        TiledMap tiledMap = managedTiledMaps.get(path);
        if (tiledMap == null) {
            tiledMap = new TiledMap(fileHandle);
            managedTiledMaps.put(path, tiledMap);
        }
        return tiledMap;
    }

    public void disposeTiledMap(TiledMap tiledMap) {
        for (Map.Entry<String, TiledMap> entry : managedTiledMaps.entrySet()) {
            if (entry.getValue().equals(tiledMap)) {
                managedTiledMaps.remove(entry.getKey());
                tiledMap.dispose();
                return;
            }
        }
    }

    public void disposeTiledMap(String internalPath) {
        disposeTiledMap(Gdx.files.internal(internalPath));
    }

    public void disposeTiledMap(FileHandle fileHandle) {
        String path = fileHandle.path();
        TiledMap tiledMap = managedTiledMaps.get(path);
        if (tiledMap != null) {
            managedTiledMaps.remove(path);
            tiledMap.dispose();
        }
    }

    public void disposeAllTiledMap() {
        for (Map.Entry<String, TiledMap> entry : managedTiledMaps.entrySet()) {
            entry.getValue().dispose();
        }
        managedTiledMaps.clear();
    }

    @Override
    public void dispose() {
        disposeAllTexture();
        disposeAllMusic();
        disposeAllSound();
        disposeAllTiledMap();
    }

}
